package cn.iscorpio;

import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

public class PrintA1B2C3 {

    static Thread t_letters = null, t_numbers = null;
    static String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static int[] numbers = IntStream.rangeClosed(1, 26).toArray();

    public static void main(String[] args) {
        LockDemo.execute();
    }

    public static class ParkDemo {

        public static void execute() {
            t_letters = new Thread(() -> {
                for (int i = 0; i < letters.length(); i++) {
                    System.out.print(letters.charAt(i));
                    LockSupport.unpark(t_numbers);
                    LockSupport.park();
                }
                LockSupport.unpark(t_numbers);
            });

            t_numbers = new Thread(() -> {
                LockSupport.park();
                for (int i = 0; i < numbers.length; i++) {
                    System.out.println(numbers[i]);
                    LockSupport.unpark(t_letters);
                    LockSupport.park();
                }
                LockSupport.unpark(t_letters);
            });

            t_letters.start();
            t_numbers.start();
        }

    }

    public static class LockDemo {
        static Lock lock = new ReentrantLock();
        static Condition c_letters = lock.newCondition();
        static Condition c_numbers = lock.newCondition();

        public static void execute() {
            t_letters = new Thread(() -> {
                try {
                    lock.lock();
                    for (int i = 0; i < letters.length(); i++) {
                        System.out.print(letters.charAt(i));
                        c_numbers.signal();
                        c_letters.await();
                    }
                    c_numbers.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            });

            t_numbers = new Thread(() -> {
                try {
                    lock.lock();
                    for (int i = 0; i < numbers.length; i++) {
                        System.out.println(numbers[i]);
                        c_letters.signal();
                        c_numbers.await();
                    }
                    c_letters.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            });

            t_letters.start();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t_numbers.start();

        }

    }

    public static class SemaphoreDemo {
        static Semaphore a = new Semaphore(1);
        static Semaphore b = new Semaphore(0);

        public static void execute() {
            t_letters = new Thread(() -> {
                for (int i = 0; i < letters.length(); i++) {
                    try {
                        a.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.print(letters.charAt(i));
                    b.release();
                }
            });

            t_numbers = new Thread(() -> {
                for (int i = 0; i < numbers.length; i++) {
                    try {
                        b.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(numbers[i]);
                    a.release();
                }
            });

            t_letters.start();

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t_numbers.start();
        }

    }

}
